/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
package org.unidata.mdm.data.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.unidata.mdm.meta.type.search.EntityIndexType;
import org.unidata.mdm.meta.type.search.RelationHeaderField;
import org.unidata.mdm.search.context.SearchRequestContext;
import org.unidata.mdm.search.service.SearchService;
import org.unidata.mdm.search.type.form.FieldsGroup;
import org.unidata.mdm.search.type.form.FormField;
import org.unidata.mdm.search.type.query.SearchQuery;
import org.unidata.mdm.system.service.TouchService;
import org.unidata.mdm.system.type.touch.Touch;
import org.unidata.mdm.system.type.touch.TouchParams;
import org.unidata.mdm.system.type.touch.Touchable;

/**
 * @author Mikhail Mikhailov on Apr 22, 2021
 */
@Component
public class DataTouchableComponent implements Touchable, InitializingBean  {
    /**
     * TS.
     */
    @Autowired
    private TouchService touchService;
    /**
     * SS.
     */
    @Autowired
    private SearchService searchService;
    /**
     * Has lookup data.
     */
    private static final Touch<Boolean> TOUCH_HAS_LOOKUP_DATA
        = Touch.builder(Boolean.class)
            .touchName("[touch-has-lookup-data]")
            .paramType("lookup-name", String.class)
            .build();
    /**
     * Has register data.
     */
    private static final Touch<Boolean> TOUCH_HAS_REGISTER_DATA
        = Touch.builder(Boolean.class)
            .touchName("[touch-has-register-data]")
            .paramType("register-name", String.class)
            .build();
    /**
     * Has register data.
     */
    private static final Touch<Boolean> TOUCH_HAS_RELATION_DATA
        = Touch.builder(Boolean.class)
            .touchName("[touch-has-relation-data]")
            .paramType("entity-name", String.class)
            .paramType("relation-name", String.class)
            .build();
    /**
     * Constructor.
     */
    public DataTouchableComponent() {
        super();
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        touchService.register(this,
                TOUCH_HAS_LOOKUP_DATA,
                TOUCH_HAS_REGISTER_DATA,
                TOUCH_HAS_RELATION_DATA);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Object touch(TouchParams<?> t) {

        if (StringUtils.equals(t.getTouch().getTouchName(), TOUCH_HAS_LOOKUP_DATA.getTouchName())) {
            return hasLookupData(t);
        } else if (StringUtils.equals(t.getTouch().getTouchName(), TOUCH_HAS_REGISTER_DATA.getTouchName())) {
            return hasRegisterData(t);
        } else if (StringUtils.equals(t.getTouch().getTouchName(), TOUCH_HAS_RELATION_DATA.getTouchName())) {
            return hasRelationData(t);
        }

        return null;
    }

    private Boolean hasLookupData(TouchParams<?> params) {

        String lookupName = params.getParam("lookup-name");
        if (StringUtils.isNotBlank(lookupName)) {

            long count = searchService.countAll(
                 SearchRequestContext.builder(EntityIndexType.RECORD, lookupName)
                    .build());

            return Boolean.valueOf(count > 0);
        }

        return Boolean.FALSE;
    }

    private Boolean hasRegisterData(TouchParams<?> params) {

        String registerName = params.getParam("register-name");
        if (StringUtils.isNotBlank(registerName)) {

            long count = searchService.countAll(
                 SearchRequestContext.builder(EntityIndexType.RECORD, registerName)
                    .build());

            return Boolean.valueOf(count > 0);
        }

        return Boolean.FALSE;
    }

    private Boolean hasRelationData(TouchParams<?> params) {

        String entityName = params.getParam("entity-name");
        String relationName = params.getParam("relation-name");
        if (StringUtils.isNotBlank(entityName) && StringUtils.isNotBlank(relationName)) {

            long count = searchService.countAll(
                 SearchRequestContext.builder(EntityIndexType.RELATION, entityName)
                     .filter(SearchQuery.formQuery(FieldsGroup.and(FormField.exact(RelationHeaderField.FIELD_RELATION_NAME, relationName))))
                     .build());

            return Boolean.valueOf(count > 0);
        }

        return Boolean.FALSE;
    }
}
